package com.td.spring.beans.factory;

import com.td.spring.aop.BeanFactoryAware;
import com.td.spring.beans.BeanDefinition;
import com.td.spring.BeanReference;
import com.td.spring.beans.PropertyValue;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author td
 * @date 2018/6/4
 */
public class AutowireCapableBeanFactory extends AbstractBeanFactory {


    @Override
    protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception {

        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }

        List<PropertyValue> propertyValues = beanDefinition.getPropertyValues().getPropertyValues();

        for (PropertyValue propertyValue : propertyValues) {

            Object value = propertyValue.getValue();
            if (value instanceof BeanReference) {
                BeanReference beanReference = (BeanReference) value;
                value = getBean(beanReference.getName());
            }
            try {
                Method declaredMethod = bean.getClass().getDeclaredMethod("set" +
                        propertyValue.getName().substring(0,1).toUpperCase() + propertyValue.getName().substring(1),value.getClass());
                declaredMethod.setAccessible(true);
                declaredMethod.invoke(bean,value);
            } catch (NoSuchMethodException e) {
                Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
                declaredField.setAccessible(true);
                declaredField.set(bean, value);
            }
        }
    }
}
